package com.juyu.miliao.authentication.config;

import javax.sql.DataSource;
import com.juyu.miliao.common.dataSource.*;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
import com.juyu.miliao.authentication.dao.redis.UserRedisDao;
import com.juyu.miliao.common.dataSource.key.DataSourceKey;
import com.juyu.miliao.common.dataSource.key.DataSourceKeyEvaluator;
import com.juyu.miliao.common.dataSource.tool.operate.OperateAspect;
import org.springframework.data.redis.core.StringRedisTemplate;

@Configuration
public class DatabaseConfig {
	@Autowired
	private ResourcePatternResolver resourcePatternResolver;
	@Autowired
	private UserRedisDao userRedisDao;

	@Bean
	public DataSourceKey dataSourceKey(){
		return new DataSourceKey();
	}
	
	@Bean
	public DataSourceKeyEvaluator dataSourceKeyEvaluator(){
		return new GlobalDataSourceKeyEvaluator(userRedisDao);
	}
	
	@Bean
	public OperateAspect switchDataSourceKeyAspect(DataSourceKey dataSourceKey, DataSourceKeyEvaluator dataSourceKeyEvaluator){
		return new OperateAspect(dataSourceKey, dataSourceKeyEvaluator);
	}
	
	@Bean
	@ConfigurationProperties("app.multiple-datasource")
	public MultipleDataSourceConfig multipleDataSourceConfig() {
		return new MultipleDataSourceConfig();
	}
	
	@Bean
	public MultipleDataSourceParser multipleDataSourceParser(MultipleDataSourceConfig multipleDataSourceConfig){
		return MultipleDataSourceParser.builder().setMultipleDataSourceConfig(multipleDataSourceConfig).build();
	}
	
	@Bean
	public MultipleDataSource dataSource(MultipleDataSourceParser multipleDataSourceParser, DataSourceKey dataSourceKey){
		MultipleDataSource multipleDataSource = new MultipleDataSource(dataSourceKey);
		multipleDataSource.setDefaultTargetDataSource(multipleDataSourceParser.getDefaultDataSource());
		multipleDataSource.setLenientFallback(false);
		multipleDataSource.setTargetDataSources(multipleDataSourceParser.getDataSourceMap());
		return multipleDataSource;
	}

	private SqlSessionFactory createSqlSessionFactory(Object key, Object dataSource)  {
	    try{
            SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
            sqlSessionFactoryBean.setDataSource((DataSource) dataSource);
            Resource[] resources = resourcePatternResolver
                    .getResources("classpath*:com/juyu/miliao/authentication/dao/mysql/*.xml");
            sqlSessionFactoryBean.setMapperLocations(resources);
            org.apache.ibatis.session.Configuration configuration = new org.apache.ibatis.session.Configuration();
            configuration.setMapUnderscoreToCamelCase(true);
            sqlSessionFactoryBean.setConfiguration(configuration);
            return sqlSessionFactoryBean.getObject();
        }catch(Exception e){
            throw new RuntimeException(e);
        }
	}

	@Bean
	public SqlSession sqlSession(DataSourceKey dataSourceKey, MultipleDataSourceParser multipleDataSourceParser) throws Exception {
        MultipleSqlSessionFactoryParser parser = MultipleSqlSessionFactoryParser.builder()
                                                    .setMultipleDataSourceParser(multipleDataSourceParser)
                                                    .setSqlSessionFactoryCreater(this::createSqlSessionFactory)
                                                    .build();
		return new MutipleSqlSessionTemplate(dataSourceKey, parser.getDefaultSqlSessionFactory(), parser.getSqlSessionFactoryMap());
	}

	@Bean
	public IdCreater idCreater(StringRedisTemplate stringRedisTemplate, MultipleDataSourceParser multipleDataSourceParser){
		return new IdCreater(stringRedisTemplate, multipleDataSourceParser);
	}

}
